package com.ibm.workplace.wcm.cqplugin.ui.preference;

import java.util.*;
import java.util.regex.*;

import org.eclipse.jface.dialogs.*;
import org.eclipse.jface.preference.*;
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.program.*;
import org.eclipse.swt.widgets.*;

import com.ibm.workplace.wcm.cqplugin.*;
import com.ibm.workplace.wcm.cqplugin.preference.*;
//import com.ibm.workplace.wcm.cqplugin.ui.composites.*;

public class AdvancedPreferencesComposite extends Composite implements SelectionListener {
    
    private Button scanIncoming = null;
    private Button scanOutgoing = null;

    private Table table = null;
    private Composite composite = null;
    private Button addButton = null;
    private Button editButton = null;
    private Button removeButton = null;
    private Button upButton = null;
    private Button downButton = null;
    private Button testButton;
    private Link helpLink;
    
    private CqQueryColumnsComposites queryColumnsComposite;

    private String previousTestString;

    public AdvancedPreferencesComposite(Composite arg0, int arg1) {
        super(arg0, arg1);

        previousTestString = "";

        initialize();
    }

    private void initialize() {
        GridLayout gridLayout = new GridLayout(2, false);
        gridLayout.marginWidth = 0;
        gridLayout.marginHeight = 0;
                
        scanIncoming = new Button(this, SWT.CHECK);
        scanIncoming.setText("Scan incoming Sametime messages for defect numbers");
        GridData data = new GridData();
        data.horizontalSpan = 2;
        scanIncoming.setLayoutData(data);
                
        scanOutgoing = new Button(this, SWT.CHECK);
        scanOutgoing.setText("Scan outgoing Sametime messages for defect numbers");
        data = new GridData();
        data.horizontalSpan = 2;
        scanOutgoing.setLayoutData(data);
        
        Label label = new Label(this, 0);
        data = new GridData();
        data.horizontalSpan = 2;
        label.setLayoutData(data);

        label = new Label(this, 0);
        label.setText("Configure patterns to search for defect numbers:");
        data = new GridData();
        data.horizontalSpan = 2;
        label.setLayoutData(data);

        table = new Table(this, SWT.BORDER);
        table.setHeaderVisible(false);
        table.setLinesVisible(false);
        TableColumn tableColumn = new TableColumn(table, SWT.NONE);
        tableColumn.setText("Pattern");
        tableColumn.setWidth(260);
        data = new GridData();
        data.widthHint = 300;
        data.heightHint = 200;
        table.setLayoutData(data);
        table.addSelectionListener(this);

        setLayout(gridLayout);

        createComposite();

        helpLink = new Link(this, 0);
        helpLink.setText("For help on building a regular expression pattern, see the Java <a>Pattern API</a>.");
        helpLink.addSelectionListener(this);
        data = new GridData();
        data.horizontalSpan = 2;
        helpLink.setLayoutData(data);
        
        label = new Label(this, 0);
        data = new GridData();
        data.horizontalSpan = 2;
        label.setLayoutData(data);
        
        
        /*ExpandBar bar = new ExpandBar(this, SWT.FLAT);
        ExpandItem item = new ExpandItem(bar, SWT.FLAT);
        item.setText("CMVC Defect Columns");*/

        label = new Label(this, 0);
        data = new GridData();
        data.horizontalSpan = 2;
        label.setLayoutData(data);
        label.setText("Configure CMVC column names:");

        queryColumnsComposite = new CqQueryColumnsComposites(this, 0);
        
        /*item.setHeight(queryColumnsComposite.computeSize(-1, -1).y);
        item.setExpanded(false);
        item.setControl(queryColumnsComposite);*/

        updateEnableStates();
    }

    /**
     * This method initializes composite	
     *
     */
    private void createComposite() {
        composite = new Composite(this, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));

        addButton = new Button(composite, SWT.NONE);
        addButton.setText("&Add");
        addButton.addSelectionListener(this);
        addButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));

        editButton = new Button(composite, SWT.NONE);
        editButton.setText("&Edit");
        editButton.addSelectionListener(this);
        editButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));

        removeButton = new Button(composite, SWT.NONE);
        removeButton.setText("&Remove");
        removeButton.addSelectionListener(this);
        removeButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));

        upButton = new Button(composite, SWT.NONE);
        upButton.setText("&Up");
        upButton.addSelectionListener(this);
        upButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));

        downButton = new Button(composite, SWT.NONE);
        downButton.setText("&Down");
        downButton.addSelectionListener(this);
        downButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));

        Label label = new Label(composite, 0);

        testButton = new Button(composite, SWT.NONE);
        testButton.setText("&Test");
        testButton.addSelectionListener(this);
        testButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));

    }

    public void widgetDefaultSelected(SelectionEvent event) {
        if (event.getSource() == table) {
            editPressed();
        }
    }

    public void widgetSelected(SelectionEvent event) {
        if (event.getSource() == addButton) {
            InputDialog dialog = new InputDialog(getShell(), "Add Pattern", "Enter new regular expression pattern:", "", new PatternValidator());
            if (dialog.open() == InputDialog.OK) {
                TableItem tableItem = new TableItem(table, 0);
                tableItem.setText(dialog.getValue());
            }
        } else if (event.getSource() == editButton) {
            editPressed();
        } else if (event.getSource() == removeButton) {
            if (table.getSelectionIndex() != -1) {
                int oldIndex = table.getSelectionIndex();
                table.remove(oldIndex);
                if (oldIndex < table.getItemCount() - 1) {
                    table.setSelection(oldIndex);
                } else if (table.getItemCount() > 0) {
                    table.setSelection(table.getItemCount() - 1);
                }
            }
        } else if (event.getSource() == upButton) {
            swapTableItems(table.getSelectionIndex(), table.getSelectionIndex() - 1);
            table.setSelection(table.getSelectionIndex() - 1);
        } else if (event.getSource() == downButton) {
            swapTableItems(table.getSelectionIndex(), table.getSelectionIndex() + 1);
            table.setSelection(table.getSelectionIndex() + 1);
        } else if (event.getSource() == helpLink) {
            Program.launch("http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html");
        } else if (event.getSource() == testButton) {
            InputDialog dialog = new InputDialog(getShell(), "Test Patterns", "Enter a sample string, which may or may not include valid defect numbers.", previousTestString, null);
            if (dialog.open() == InputDialog.OK) {
                previousTestString = dialog.getValue();
                
                /*
                XmlStringBugIdFinder finder = XmlStringBugIdFinder.newInstance(buildPatternString());
                IBugIdFinderResult[] results = finder.find("<div>" + dialog.getValue() + "</div>"); // HACK
                if (results == null || results.length == 0) {
                    MessageDialog.openInformation(getShell(), "Test Patterns", "No results found.");
                } else {
                    StringBuffer buffer = new StringBuffer();
                    buffer.append("The following defect numbers were found:\n\n");
                    for (int i = 0; i < results.length; i++) {
                        buffer.append("* " + results[i].getId() + "\n");
                    }
                    MessageDialog.openInformation(getShell(), "Test Patterns", buffer.toString());
                }
                */
            }
        }

        updateEnableStates();
    }

    private void editPressed() {
        if (table.getSelectionIndex() == -1) return;

        InputDialog dialog = new InputDialog(getShell(), "Edit Pattern", "Regular expression pattern:", table.getSelection()[0].getText(), new PatternValidator());
        if (dialog.open() == InputDialog.OK) {
            table.getSelection()[0].setText(dialog.getValue());
        }
    }

    private void updateEnableStates() {
        editButton.setEnabled(table.getItemCount() > 0 && table.getSelectionCount() > 0);
        removeButton.setEnabled(table.getItemCount() > 0 && table.getSelectionCount() > 0);
        upButton.setEnabled(table.getItemCount() > 1 && table.getSelectionIndex() > 0);
        downButton.setEnabled(table.getItemCount() > 1 && table.getSelectionIndex() != -1 && table.getSelectionIndex() < table.getItemCount() - 1);
        testButton.setEnabled(table.getItemCount() > 0);
    }

    private static class PatternValidator implements IInputValidator {

        public String isValid(String arg0) {
            try {
                if (arg0.indexOf('#') != -1) {
                    return "Pound sign not allowed.";
                }
                java.util.regex.Pattern.compile(arg0);
            } catch (PatternSyntaxException pse) {
                return "Invalid pattern: " + pse.getMessage();
            } catch (Exception ex) {
                return ex.getMessage();
            }

            return null;
        }

    }

    public void setPatterns(String[] patterns) {
        table.removeAll();

        if (patterns != null) {
            for (int i = 0; i < patterns.length; i++) {
                TableItem item = new TableItem(table, 0);
                item.setText(patterns[i]);
            }
        }
    }

    public String[] getPatterns() {
        String[] ret = new String[table.getItemCount()];

        for (int i = 0; i < table.getItemCount(); i++) {
            ret[i] = table.getItem(i).getText();
        }

        return ret;
    }

    public void init(IPreferenceStore store, boolean useDefault) {
        String str = null;
        if (useDefault) {
            str = store.getDefaultString(BugInfoPreferenceConstants.PREF_BUG_PATTERNS);
        } else {
            str = store.getString(BugInfoPreferenceConstants.PREF_BUG_PATTERNS);
        }

        StringTokenizer st = new StringTokenizer(str, BugInfoPreferenceConstants.BUG_PATTERN_SEPARATOR);
        String[] patterns = new String[st.countTokens()];
        int index = 0;
        while (st.hasMoreElements()) {
            patterns[index] = st.nextToken();
            index++;
        }
        setPatterns(patterns);

        updateEnableStates();
                
        scanIncoming.setSelection(store.getBoolean(BugInfoPreferenceConstants.PREF_SCAN_INCOMING));
        scanOutgoing.setSelection(store.getBoolean(BugInfoPreferenceConstants.PREF_SCAN_OUTGOING));
        
        queryColumnsComposite.init(store);
    }

    private String buildPatternString() {
        String[] patterns = getPatterns();
        String patternString = "";
        if (patterns != null) {
            for (int i = 0; i < patterns.length; i++) {
                patternString = patternString + patterns[i] + (i < patterns.length - 1 ? BugInfoPreferenceConstants.BUG_PATTERN_SEPARATOR : "");
            }
        }
        return patternString;
    }

    public void store(IPreferenceStore store) {
        String patternString = buildPatternString();
        store.setValue(BugInfoPreferenceConstants.PREF_BUG_PATTERNS, patternString);
        
        store.setValue(BugInfoPreferenceConstants.PREF_SCAN_INCOMING, scanIncoming.getSelection());
        store.setValue(BugInfoPreferenceConstants.PREF_SCAN_OUTGOING, scanOutgoing.getSelection());
        
        queryColumnsComposite.store(store);
    }

    private void swapTableItems(int index1, int index2) {
        String val1 = table.getItem(index1).getText();
        table.getItem(index1).setText(table.getItem(index2).getText());
        table.getItem(index2).setText(val1);
    }

}
